package manongfanshen.memory_model.volatile_atomic;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.stream.IntStream;

import static org.assertj.core.api.Assertions.assertThat;

/**
 * @author ChangLiang
 * @date 2020/3/19
 */
public class MainTestV1 {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private static final Object LOCK = new Object();

    /**
     * synchronized: ensure visibility, atomic, so not need volatile
     * but not ensure orderly
     *
     */
    int value = 0;

    @Test
    @DisplayName("test volatile atomic")
    public void test(){

        int initActiveCount = Thread.activeCount();
        logger.info("initActiveCount:{}", initActiveCount);

        // start 10 thread
        IntStream.rangeClosed(1,10).forEach(i->new Thread(String.valueOf(i)){
            @Override
            public void run() {
                for (int j = 0; j < 1000; j++) {
//                    synchronized (LOCK) {
//                        synchronized (MainTestV1.class){
                        synchronized (this.getClass()){
                        value++;
                    }
                }
            }
        }.start());

        // ensure 10 thread start
//        ThreadUtil.sleepForMilliSeconds(10000);

        // ensure 10 thread finish
        while (Thread.activeCount() > initActiveCount) {
            Thread.yield();
        }

        logger.info("finalActiveCount:{}", Thread.activeCount());

        logger.info("value:{}", value);
        assertThat(value).isEqualTo(10000);
    }
}
